package cn.geekyspace.scanhive.serial.manager;

import cn.geekyspace.scanhive.serial.receiver.ScannerDataReceiver;
import cn.geekyspace.scanhive.utils.UIUpdater;
import com.fazecast.jSerialComm.SerialPort;
import javafx.scene.paint.Color;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 扫描仪（扫码枪）串口管理
 */
@Data
@Slf4j
@Component
public class ScannerSerialPortManager {

    // 扫码枪串口名称
    private static final String TARGET_PORT_NAME = "Prolific USB-to-Serial Comm Port";

    // 使用线程安全的列表存储已连接的串口
    private List<SerialPort> scannerPorts = new CopyOnWriteArrayList<>();

    // 注入UI更新器
    private final UIUpdater uiUpdater;

    // 注入扫描仪（扫码枪）数据接收处理器
    private final ScannerDataReceiver scannerDataReceiver;


    /**
     * 定时扫描串口并连接目标串口
     */
    @Scheduled(fixedRate = 2000)
    public void scanPorts() {
        // 获取所有串口对象
        SerialPort[] ports = SerialPort.getCommPorts();

        // 遍历所有串口，检查是否是目标串口并尝试连接
        for (SerialPort port : ports) {
            if (port.getDescriptivePortName().contains(TARGET_PORT_NAME) && !isPortConnected(port)) {
                // 设置串口参数
                port.setComPortParameters(115200, 8, 1, 0);  // 波特率、数据位、停止位、校验位
                port.setComPortTimeouts(SerialPort.TIMEOUT_READ_BLOCKING, 1000, 0);  // 设置读取超时

                // 尝试打开串口
                if (port.openPort()) {
                    scannerPorts.add(port);
                    String successMessage = "扫码枪连接成功: 串口号 = " + port.getSystemPortName() + ", 串口描述 = " + port.getDescriptivePortName();
                    log.info(successMessage);
                    uiUpdater.setLogMessage(successMessage, Color.GREEN);

                    // 启动数据接收
                    scannerDataReceiver.startReceivingData(port);
                } else {
                    String failureMessage = "扫码枪连接失败: 串口号 = " + port.getSystemPortName() + ", 串口描述 = " + port.getDescriptivePortName();
                    log.warn(failureMessage); // 记录日志
                    uiUpdater.setLogMessage(failureMessage, Color.ORANGE);
                }
            }
        }

        // 移除断开的串口
        checkAndRemoveDisconnectedPorts();
    }

    /**
     * 检查并移除断开的串口
     */
    private void checkAndRemoveDisconnectedPorts() {
        for (SerialPort port : scannerPorts) {
            // 如果串口已经断开连接，移除该串口
            if (!port.isOpen()) {
                String disconnectMessage = "扫码枪断开连接: 串口号 = " + port.getSystemPortName() + ", 串口描述 = " + port.getDescriptivePortName();
                log.info(disconnectMessage);
                uiUpdater.setLogMessage(disconnectMessage, Color.RED);  // 用红色显示断开连接信息

                // 停止数据接收
                scannerDataReceiver.stopReceivingData();

                scannerPorts.remove(port);
            }
        }
    }

    /**
     * 检查串口是否已经连接
     */
    private boolean isPortConnected(SerialPort port) {
        return scannerPorts.stream().anyMatch(p -> p.getSystemPortName().equals(port.getSystemPortName()));
    }

    /**
     * 释放所有已连接的串口资源
     */
    public void releaseResources() {
        for (SerialPort port : scannerPorts) {
            if (port.isOpen()) {
                log.info("关闭扫码枪连接的串口: " + port.getSystemPortName());
                port.closePort();
            }
        }
        scannerPorts.clear(); // 清空列表
    }

}
